package com.heiban.springboot.controller;

import com.heiban.springboot.bean.Order;
import com.heiban.springboot.repository.OrderRepository;
import com.heiban.springboot.sdk.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


@Controller
public class OrderController {

    @Autowired
    OrderRepository orderRepository;

    Logger logger = LoggerFactory.getLogger(getClass());//记录器


    //商品首页渲染
    @RequestMapping({"/","/index.html"})
    public String index() {
        return "index";
    }

    //订单列表渲染
    @RequestMapping("/information.html")
    public String orderdetails(ModelMap model) {

        List<Order> all = orderRepository.findAll();

        model.put("orderall",all);

        return "information";
    }


    //订单发起方法
    @RequestMapping("/paymethod")
    public String paymethod(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String username = request.getParameter("username");//获取表单提交的用户名
        String commodity = request.getParameter("commodity");//获取表单提交的商品名称
        String money = commodity.equals("商品1")?"1":commodity.equals("商品2")?"2":"3";//通过商品名称获取价格
        String nowtime = String.valueOf(System.currentTimeMillis());//用于商户订单号
        String userIp = getIpAddr(request);//获取用户的IP地址

        logger.trace("获取到用户的IP地址："+userIp);



        //将订单信息保存到数据库 等待支付成功回调再进行处理
        Order order = new Order();
        order.setUsername(username);
        order.setMoney(money);
        order.setCommodity(commodity);
        order.setOut_trade_no(nowtime);//设置商户订单号
        orderRepository.save(order);//保存到数据库


        logger.trace("成功进入支付方法");

        MyWXPayConfig config = new MyWXPayConfig();//配置类
        WXPay wxpay = new WXPay(config);//统一下单接口

        Map<String, String> data = new HashMap<String, String>();

        data.put("device_info", "WEB"); //设备号 PC网页或公众号内支付可以传"WEB"
        data.put("nonce_str",WXPayUtil.generateNonceStr());//随机字符串
        data.put("body", commodity); //商品描述
        data.put("out_trade_no", nowtime); //商户订单号
        data.put("total_fee", money); //标价金额 单位是分
        data.put("spbill_create_ip", userIp); //用户的客户端IP
        data.put("notify_url", "http://heibanyufenbi.xyz/notify_url"); //通知地址
        data.put("trade_type", "MWEB");  // 交易类型  JSAPI--JSAPI支付（或小程序支付）、NATIVE--Native支付、APP--app支付，MWEB--H5支付

        try {
            Map<String, String> resp = wxpay.unifiedOrder(data);
            logger.trace(resp.toString());
            logger.trace("需要请求的地址："+resp.get("mweb_url"));

            //跳转URL  //redirect_url则为返回至指定页面
            String url = resp.get("mweb_url")+"&redirect_url=http://heibanyufenbi.xyz/information.html";

            //重定向页面
            return "redirect:"+url;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    @ResponseBody
    @RequestMapping("/notify_url")
    public String notify_url(HttpServletRequest request, HttpServletResponse response) throws Exception {

        logger.trace("支付信息回调中");

        String notifyData = "";
        try{

            InputStream inputStream = request.getInputStream();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[2048];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }

            notifyData = new String(outputStream.toByteArray(), "utf-8");// 支付结果通知的xml格式数据

            //关闭流
            outputStream.close();
            inputStream.close();

            logger.trace("获取xml格式数据成功：\n"+notifyData);

        }catch (Exception e){
            logger.trace("解析回调数据发生异常");
        }



        MyWXPayConfig config = new MyWXPayConfig();//配置类

        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
        logger.trace("notifyMap = "+notifyMap);
        logger.trace("sign = "+notifyMap.get("sign"));

        if (WXPayUtil.isSignatureValid(notifyMap,config.getKey(),WXPayConstants.SignType.HMACSHA256)) {//HMACSHA256签名验证方法
//        if (WXPayUtil.isSignatureValid(notifyMap,config.getKey())) {//MD5签名验证方法
            // 签名正确
            // 进行处理。
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功

            String out_trade_no = notifyMap.get("out_trade_no");//获取商户订单号
            String transaction_id = notifyMap.get("transaction_id");//微信支付订单号

            //处理标记付款成功
            Order order = orderRepository.findByOuttradeno(out_trade_no);
            if(order.getTrade_no()==null){
                order.setPlay(1);//设置为支付成功
                order.setTrade_no(transaction_id);//设置微信支付订单号
                orderRepository.save(order);//保存到数据库
                logger.trace("回调验证成功 业务代码已经处理");
            }



            //返回给微信的数据 标志成功
            Map<String,String> map = new HashMap<String, String>();
            map.put("return_code","SUCCESS");//SUCCESS表示商户接收通知成功并校验成功
            map.put("return_msg","OK");

            logger.trace("验签成功");

            return WXPayUtil.mapToXml(map);

        }
        else {
            // 签名错误，如果数据里没有sign字段，也认为是签名错误

            //返回给微信的数据 标志失败
            Map<String,String> map = new HashMap<String, String>();
            map.put("return_code","FAIL");
            map.put("return_msg","NO");

            logger.trace("验签失败");

            return WXPayUtil.mapToXml(map);
        }


    }



    //获取用户的IP地址
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    // 根据网卡取本机配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress="";
        }
        // ipAddress = this.getRequest().getRemoteAddr();

        return ipAddress;
    }

}
